package graphiceditor;

import graphiceditor.interfaces.IMememnto;

import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

public class MainForm extends JFrame {

    private static final long serialVersionUID = 9015224629649926984L;

    private EventBus eventBus = new EventBus("Shape and Color bus");

    private DefaultListModel mementos;

    public MainForm() {
	initialize();
	setLocationByPlatform(true);
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	setSize(800, 600);
	setVisible(true);
    }

    private void initialize() {
	setLayout(new GridBagLayout());

	GridBagConstraints c = new GridBagConstraints();
	c.fill = GridBagConstraints.BOTH;
	c.anchor = GridBagConstraints.WEST;
	c.gridx = 0;
	c.gridy = 0;
	c.weightx = 1.0;
	c.weighty = 1.0;
	c.insets = new Insets(10, 10, 10, 10);
	DrawingPanel canvas = new DrawingPanel();
	eventBus.register(canvas);
	canvas.subscribeOnChanges(this);

	getContentPane().add(canvas, c);

	c = new GridBagConstraints();
	c.fill = GridBagConstraints.NONE;
	c.anchor = GridBagConstraints.WEST;
	c.gridx = 0;
	c.gridy = 1;
	c.weightx = 0;
	c.weighty = 0;
	c.insets = new Insets(10, 10, 10, 10);
	getContentPane().add(createShapeRadioBattonsPanel(), c);

	mementos = new DefaultListModel();
	mementos.addElement(canvas.getInitialMemento());
	final JList mementoListPanel = new JList(mementos);
	mementoListPanel.addListSelectionListener(new ListSelectionListener() {

	    @Override
	    public void valueChanged(ListSelectionEvent e) {
		selectionChanged(e.getLastIndex());
		mementoListPanel.clearSelection();
	    }
	});
	c = new GridBagConstraints();
	c.fill = GridBagConstraints.BOTH;
	c.anchor = GridBagConstraints.WEST;
	c.gridheight = 2;
	c.gridx = 1;
	c.gridy = 0;
	c.weightx = 0.2;
	c.weighty = 1.0;
	c.insets = new Insets(10, 10, 10, 10);
	getContentPane().add(new JScrollPane(mementoListPanel), c);
    }

    private Component createShapeRadioBattonsPanel() {
	JRadioButton lineButton = new JRadioButton("Line");
	lineButton.setSelected(true);

	JRadioButton rectButton = new JRadioButton("Rectangle");

	JRadioButton ellipseButton = new JRadioButton("Ellipse");

	JRadioButton blackButton = new JRadioButton("Black");
	blackButton.setSelected(true);

	JRadioButton redButton = new JRadioButton("Red");

	JRadioButton greenButton = new JRadioButton("Green");

	// Group the radio buttons.
	ButtonGroup shapes = new ButtonGroup();
	shapes.add(lineButton);
	shapes.add(rectButton);
	shapes.add(ellipseButton);

	// Group the radio buttons.
	ButtonGroup color = new ButtonGroup();
	color.add(blackButton);
	color.add(redButton);
	color.add(greenButton);

	lineButton.addActionListener(new ShapeListener(ShapeType.LINE));
	rectButton.addActionListener(new ShapeListener(ShapeType.RECTANGLE));
	ellipseButton.addActionListener(new ShapeListener(ShapeType.ELLIPSE));

	blackButton.addActionListener(new ColorListener(Color.BLACK));
	redButton.addActionListener(new ColorListener(Color.RED));
	greenButton.addActionListener(new ColorListener(Color.GREEN));

	JPanel radioPanel = new JPanel(new GridLayout(0, 2));
	radioPanel.add(lineButton);
	radioPanel.add(blackButton);
	radioPanel.add(rectButton);
	radioPanel.add(redButton);
	radioPanel.add(ellipseButton);
	radioPanel.add(greenButton);
	return radioPanel;
    }

    private class ShapeListener implements ActionListener {

	private final ShapeType shape;

	public ShapeListener(ShapeType shape) {
	    this.shape = shape;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
	    shapeTypeChanged(shape);
	}
    }

    private class ColorListener implements ActionListener {

	private final Color color;

	public ColorListener(Color color) {
	    this.color = color;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
	    colorTypeChanged(color);
	}
    }

    public static void main(String[] args) {
	new MainForm();
    }

    private void shapeTypeChanged(ShapeType newShape) {
	eventBus.post(newShape);
    }

    private void colorTypeChanged(Color newColor) {
	eventBus.post(newColor);
    }

    @Subscribe
    public void stateChanged(IMememnto newState) {
	mementos.addElement(newState);
    }

    private void selectionChanged(int newSelectionIndex) {
	if (newSelectionIndex < mementos.size()) {
	    Object newSelection = mementos.get(newSelectionIndex);
	    eventBus.post(newSelection);
	    int fromIndex = newSelectionIndex + 1;
	    if (fromIndex < mementos.size())
		mementos.removeRange(fromIndex, mementos.size() - 1);
	}
    }
}
